import os
import json
import time
from typing import Dict, Any, List

from PyQt5.QtWidgets import QMessageBox

try:
    import requests
except Exception:  # requests may be installed later; guard import for static analysis
    requests = None


DATA_DIR = os.path.join("data")
ASSETS_HEROES = os.path.join("assets", "heroes")
ASSETS_BATTLES = os.path.join("assets", "battles")
DATA_FILE = os.path.join(DATA_DIR, "data.json")
MESSAGES_FILE = os.path.join(DATA_DIR, "messages.json")


HERO_NAMES = [
    ("001", "杨靖宇"),
    ("002", "赵一曼"),
    ("003", "左权"),
    ("004", "张自忠"),
    ("005", "戴安澜"),
    ("006", "彭雪枫"),
    ("007", "李兆麟"),
    ("008", "彭德怀"),
    ("009", "马本斋"),
    ("010", "谢子长"),
    ("011", "邓铁梅"),
    ("012", "周保中"),
    ("013", "王二小"),
    ("014", "陈树湘"),
    ("015", "杨成武"),
    ("016", "冯仲云"),
]

BATTLES = [
    ("B001", "平型关大捷", 1937, "八路军首次取得重大胜利，极大鼓舞全国士气。", "山西平型关"),
    ("B002", "台儿庄战役", 1938, "重创侵华日军，鼓舞全国抗战信心。", "山东台儿庄"),
    ("B003", "百团大战", 1940, "打击华北交通线，展示敌后抗战力量。", "华北地区"),
    ("B004", "淞沪会战", 1937, "粉碎敌军速战速决意图，牵制大量兵力。", "上海、苏州河沿线"),
    ("B005", "长沙会战", 1939, "重创日军，稳固抗战信心。", "湖南长沙"),
    ("B006", "昆仑关战役", 1939, "桂南会战关键一役，收复昆仑关。", "广西南宁昆仑关"),
]

SPIRIT_TEXTS = [
    "国家存亡，匹夫有责",
    "不畏强敌，宁死不屈",
    "团结一致，誓死抗争",
    "坚忍不拔，浴血奋战",
    "同仇敌忾，保家卫国",
    "视死如归，英勇无畏",
    "前赴后继，血脉相传",
    "民族独立，人民解放",
]

PEACE_TEXTS = [
    "珍爱和平，反对侵略",
    "合作共赢，共创未来",
    "铭记历史，珍惜当下",
    "让世界永无战争",
]


def ensure_dirs() -> None:
    os.makedirs(DATA_DIR, exist_ok=True)
    os.makedirs(ASSETS_HEROES, exist_ok=True)
    os.makedirs(ASSETS_BATTLES, exist_ok=True)


def seed_data() -> Dict[str, Any]:
    heroes = []
    for hid, name in HERO_NAMES:
        heroes.append({
            "id": hid,
            "name": name,
            "birth": None,
            "death": None,
            "intro": f"{name} 为抗日作出突出贡献。",
            "contribution": "坚定抗战、鼓舞民众、保家卫国。",
            "quote": "青山处处埋忠骨，何须马革裹尸还。",
            "image": f"./assets/heroes/{hid}.png",
        })

    battles = []
    for bid, name, year, summary, location in BATTLES:
        battles.append({
            "id": bid,
            "name": name,
            "year": year,
            "summary": summary,
            "location": location,
            "image": f"./assets/battles/{bid}.png",
        })

    return {
        "heroes": heroes,
        "battles": battles,
        "spirit": SPIRIT_TEXTS,
        "peace": PEACE_TEXTS,
    }


def maybe_create_messages():
    if not os.path.exists(MESSAGES_FILE):
        with open(MESSAGES_FILE, "w", encoding="utf-8") as f:
            json.dump({"messages": []}, f, ensure_ascii=False, indent=2)


def download_if_missing(url: str, dest_path: str) -> None:
    if os.path.exists(dest_path):
        return
    os.makedirs(os.path.dirname(dest_path), exist_ok=True)
    if requests is not None:
        try:
            resp = requests.get(url, timeout=5)
            if resp.status_code == 200 and resp.content:
                with open(dest_path, "wb") as f:
                    f.write(resp.content)
                return
        except Exception:
            pass
    _write_placeholder_png(dest_path)


def _write_placeholder_png(dest_path: str) -> None:
    # 1x1 solid red PNG (base64-encoded), universally valid
    import base64
    png_b64 = (
        b"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMB/axh1iQAAAAASUVORK5CYII="
    )
    try:
        with open(dest_path, "wb") as f:
            f.write(base64.b64decode(png_b64))
    except Exception:
        pass


def auto_download_assets(data: Dict[str, Any]) -> None:
    # 严格遵循“不要下载”要求：仅本地生成占位图片文件，确保离线可用
    print("使用本地占位图，不进行任何联网下载")
    for h in data.get("heroes", []):
        dest = h.get("image")
        if dest and not os.path.exists(dest):
            _write_placeholder_png(dest)
    for b in data.get("battles", []):
        dest = b.get("image")
        if dest and not os.path.exists(dest):
            _write_placeholder_png(dest)


def ensure_data_files():
    """
    确保数据文件存在并且结构正确。
    如果文件不存在或损坏，则使用 seed_data() 创建默认数据。
    """
    # 1. 检查文件是否存在
    if os.path.exists(DATA_FILE):
        try:
            # 2. 尝试加载并验证现有数据
            with open(DATA_FILE, 'r', encoding='utf-8') as f:
                data = json.load(f)

            # 确保加载的数据是一个字典，并且包含必要的键
            if isinstance(data, dict) and all(k in data for k in ["heroes", "battles", "spirit", "peace"]):
                print("数据文件已加载并验证。")
                return data
            else:
                print("警告：数据文件格式不正确或内容缺失，将重新生成。")

        except (json.JSONDecodeError, Exception) as e:
            print(f"警告：读取数据文件时出错 ({e})，将重新生成。")

    # 3. 如果文件不存在、格式错误或内容缺失，则创建默认数据
    print("正在生成默认数据文件...")
    data = seed_data()  # seed_data() 返回的是一个结构正确的字典

    # 4. 将生成的数据写入文件
    try:
        with open(DATA_FILE, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=4)
        print("默认数据文件已创建。")
    except Exception as e:
        print(f"错误：无法写入数据文件！原因: {e}")
        # 即使写入失败，也返回内存中的默认数据，让程序能继续运行
        return data

    return data


def load_messages():
    """
    从 MESSAGES_FILE 文件中加载所有留言。
    如果文件不存在或为空，则返回一个空列表。
    """
    print(f"DEBUG: 尝试加载留言文件，路径: {os.path.abspath(MESSAGES_FILE)}")

    if not os.path.exists(MESSAGES_FILE):
        print(f"DEBUG: 留言文件 '{MESSAGES_FILE}' 不存在，将返回空列表。")
        return []

    try:
        with open(MESSAGES_FILE, 'r', encoding='utf-8') as f:
            # messages.json 的结构是 {"messages": [...]}
            data = json.load(f)
            messages = data.get("messages", [])
            if isinstance(messages, list):
                print(f"DEBUG: 成功加载 {len(messages)} 条留言。")
                return messages
            else:
                error_msg = f"警告: '{MESSAGES_FILE}' 文件格式不正确，'messages' 字段应为列表。"
                print(error_msg)
                _show_error("数据文件错误", error_msg)
                return []
    except json.JSONDecodeError as e:
        error_msg = f"文件 '{MESSAGES_FILE}' JSON格式错误: {e}\n可能是文件为空或内容损坏。"
        print(error_msg)
        _show_error("JSON解析错误", error_msg)
        return []
    except Exception as e:
        error_msg = f"读取文件 '{MESSAGES_FILE}' 时发生未知错误: {e}"
        print(error_msg)
        _show_error("读取文件错误", error_msg)
        return []


def append_message(name: str, content: str, time_str: str) -> None:
    """
    将一条新留言追加到 MESSAGES_FILE 文件中。
    """
    print(f"DEBUG: 尝试追加留言: {name} - {content[:20]}...")

    # 确保目录和文件存在
    ensure_dirs()
    maybe_create_messages()

    # 读取现有留言
    messages = load_messages()

    new_message = {
        "name": name,
        "content": content,
        "time": time_str
    }

    messages.append(new_message)

    # 写回文件
    try:
        # 注意：写入的是 {"messages": messages} 这个结构
        with open(MESSAGES_FILE, 'w', encoding='utf-8') as f:
            json.dump({"messages": messages}, f, ensure_ascii=False, indent=2)
        print(f"DEBUG: 成功写入留言文件，当前共 {len(messages)} 条留言。")
    except Exception as e:
        error_msg = f"错误：无法写入留言文件 '{MESSAGES_FILE}'。\n请检查文件夹权限或是否被其他程序锁定。\n原因: {e}"
        print(error_msg)
        _show_error("写入文件失败", error_msg)


def _show_error(title, message):
    """一个辅助函数，用于在任何地方显示错误弹窗"""
    # 获取全局应用实例，如果没有则不显示（避免在非GUI环境下出错）
    from PyQt5.QtWidgets import QApplication
    app = QApplication.instance()
    if app is not None:
        msg_box = QMessageBox()
        msg_box.setIcon(QMessageBox.Critical)
        msg_box.setWindowTitle(title)
        msg_box.setText(message)
        msg_box.exec_()
    else:
        # 如果没有GUI实例，就打印到控制台
        print(f"ERROR: {title} - {message}")

